let someValue: any = "this is a string";

let strLength1: number = (<string>someValue).length;
// 如果要写断言，建议用as，因为上面的形式在react中会有歧义。尖括号语法与JSX的标签语法相冲突
let strLength2: number = (someValue as string).length;

type MyType = string | number | boolean;

function getLength(type: MyType) {
  console.log((type as string).length);
}
getLength("hello world");

type Student = { name: string; score: number };
type Teacher = { name: string; age: number; subject: string };
type Person = Student | Teacher;

function print(person: Person) {
  console.log(person.name);
  console.log((person as Student).score);
}

class Animal {
  eat() {
    console.log("animal eat");
  }
}

class Dog extends Animal {
  eat() {
    console.log("dog eat");
  }
  bark() {
    console.log("dog bark");
  }
}

class Cat extends Animal {
  eat() {
    console.log("cat eat");
  }
  meow() {
    console.log("cat meow");
  }
}

function feed(animal: Animal) {
  (animal as Cat).meow();
}

function feedAnimal(animal: Animal) {
  if (animal instanceof Dog) {
    animal.bark();
  } else if (animal instanceof Cat) {
    animal.meow();
  } else {
    animal.eat();
  }
}

/* const inputDom = document.querySelector("input") as HTMLInputElement;
inputDom.addEventListener("change", e => { 
  console.log((e.target as HTMLInputElement).value)
}) */

const obj = {
  name: "jack",
  age: 18,
};

(obj as any).sex = "男";

console.log((obj as any).sex);

// (window as any).foo = 1;

/* export { }
declare global { 
  interface Window { 
    foo: number
  }
}
window.foo = 1; */

// 第三方API或者历史遗留问题，any或者unknown类型的存在
function getData(id: number): any {
  return {
    id: 1,
    name: "jack",
    age: 18,
  };
}

interface User {
  id: number;
  name: string;
  age: number;
}

const user = getData(1) as User;
console.log(user.name);

let str = "123";
// let n = str as number; // error

let str1: "hello" = "hello";
let str2 = "hello";

str2 = str1;
// str2 = str1 as string;

str1 = str2 as "hello";

let a: Animal = new Animal();
let b: Dog = new Dog();

// a = b;
b = a as Dog;
b.eat();

// b.bark(); // 是非常不安全的，因为b的类型是Animal，但是bark方法是Dog的方法

let maybeString: string | null = "hello";
let definitelyString = maybeString!;

function getRandom(length?: number) {
  if (!length) {
    return undefined;
  }

  return Math.random().toString(36).slice(-length);
}
let s = getRandom(6);
// 可以使用类型断言
(s as string).charAt(0);
// 由于就是字符串和非空的处理，可以使用非空断言
s!.charAt(0);

type Box = {
  id: number;
  name: string;
};

function getBox(): Box | undefined {
  if (Math.random() > 0.5) {
    return {
      id: 1,
      name: "box1",
    };
  }
  return undefined;
}

function createProduction(box: Box) {
  // todos...
}

createProduction(getBox() as Box);
// 非空断言
createProduction(getBox()!);

let str3 = "123Hello";
let n = str3 as unknown as number;
console.log(n);

// AnyScript

// as const
let strConst = "hello" as const;
// strConst = "world"; // error

let arr = [1, 2, 3] as const;

let objConst = { x: 10, y: 20 } as const;
// objConst.x = 100; // error

const person = {
  id: 1,
  name: "jack",
  address: {
    city: "成都",
    province: "四川",
  },
} as const;

const roles = ["角色列表", "用户删除", "用户查询", "权限详情"] as const

type Role = typeof roles[number];
